/**
 * \brief  Client-side region manager session interface
 * \author Christian Helmuth
 * \date   2006-07-11
 */

/*
 * Copyright (C) 2006-2009 Christian Helmuth
 * Genode Labs, Feske & Helmuth Systementwicklung GbR
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU General Public License version 2.
 */

#ifndef _INCLUDE__RM_SESSION__CLIENT_H_
#define _INCLUDE__RM_SESSION__CLIENT_H_

#include <rm_session/capability.h>
#include <base/ipc.h>
#include <base/lock.h>

namespace Genode {

	class Rm_session_client : public Rm_session
	{
		private:

			Msgbuf<256> _snd_msg, _rcv_msg;
			Ipc_client  _ipc_client;
			Lock        _lock;

		public:

			/**
			 * Constructor
			 */
			explicit Rm_session_client(Rm_session_capability session)
			: _ipc_client(session, &_snd_msg, &_rcv_msg) { }


			/**************************************
			 ** Region manager session interface **
			 **************************************/

			void *attach(Dataspace_capability ds, size_t size,
			             off_t offset, bool use_local_addr, addr_t local_addr)
			{
				Lock::Guard lock_guard(_lock);
				void *result = 0;

				switch (_ipc_client << ATTACH
				                    << ds << size << offset << use_local_addr << local_addr
				                    << IPC_CALL
				                    >> result) {

				/* translate error codes to exception types */
				case -1: throw Invalid_dataspace();
				case -2: throw Region_conflict();
				default: break;
				}
				return result;
			}

			void detach(void *local_addr)
			{
				Lock::Guard lock_guard(_lock);
				_ipc_client << DETACH << local_addr << IPC_CALL;
			}

			Thread_capability add_client(Thread_capability thread)
			{
				Lock::Guard lock_guard(_lock);
				Thread_capability result;

				switch (_ipc_client << ADD_CLIENT << thread
				                    << IPC_CALL >> result) {

				/* translate error codes to exception types */
				case -1: throw Invalid_thread();
				case -2: throw Out_of_memory();
				default: break;
				}
				return result;
			}

			void fault_handler(Signal_receiver_capability handler)
			{
				Lock::Guard lock_guard(_lock);
				_ipc_client << FAULT_HANDLER << handler << IPC_CALL;
			}

			State state()
			{
				Lock::Guard lock_guard(_lock);
				State result;
				_ipc_client << STATE << IPC_CALL >> result;
				return result;
			}

			Dataspace_capability dataspace()
			{
				Lock::Guard lock_guard(_lock);
				Dataspace_capability result;
				_ipc_client << DATASPACE << IPC_CALL >> result;
				return result;
			}
	};
}

#endif /* _INCLUDE__RM_SESSION__CLIENT_H_ */
